// Copyright 2010 Google Inc. All Rights Reserved.

package com.google.zahra.testmanager;

import com.google.zahra.util.Util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;

import commonj.work.Work;

/**
 * This class represents one item of Test. Test activities are placed inside the
 * {@code run} method. The {@code failed} flag should be set to true if the test
 * threw an exception
 *
 * @author arthurkok@google.com (Your Name Here) *
 */
public class Test implements Work {

  public final String file;
  public final String name;
  public final int os;
  public final int retries;
  public final int jobID;

  public boolean failed;
  public int status;

  public String testOutput;
  private String tempPath = "";
  
  Process proc = null;

  public Test(String file, String name, int os, int retries, int jobID) {
    this.file = file;
    this.name = name;
    this.os = os;
    this.retries = retries;
    this.jobID = jobID;
    this.testOutput = "";

  }

  public synchronized void run() {
      tempPath = System.getProperty("user.dir") + "/tmp/";

    try {
      writeFile();
      runPython();
    } catch (IOException e) {
      e.printStackTrace();
      synchronized (testOutput) {
        testOutput += Util.stackTraceToString(e);
      }
      failed = true;
    } finally {
      deleteFile();
    }
    System.out.println(String.format("Running: %d", jobID));
  }

  /**
   * Writes the python code to a file so that it can execute
   * @throws IOException
   */
  public void writeFile() throws IOException {

    System.out.println(tempPath);

    File d = new File(tempPath);
    if (!d.exists()) {
      d.mkdir();
    }

    d = new File(tempPath + "/" + jobID);
    if (!d.exists()) {
      d.mkdir();
    }

    FileWriter fw = new FileWriter(tempPath + "/" + jobID + "/test.py");
    BufferedWriter out = new BufferedWriter(fw);
    out.write(file);
    out.close();
  }

  /**
   * Clean up and delete the python file and directories created
   */
  public void deleteFile() {

    File f = new File(tempPath + "/" + jobID + "/test.py");
    if (f.exists()) {
      f.delete();
    }
    File d = new File(tempPath + "/" + jobID);
    if (d.exists()) {
      d.delete();
    }
    d = new File(tempPath);
    if (d.exists()) {
      d.delete();
    }
  }
  
  /**
   * Executes the python script stored in the test
   */
  public void runPython() {
    
    try {

      // Creates a shell and executes python
      proc = Runtime.getRuntime().exec("python " + tempPath + "/" + jobID + "/test.py");

      if (proc != null) {
        
        // Reads the output from the shell
        BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        StringBuffer stringBuffer = new StringBuffer();
        String line;
        while ((line = in.readLine()) != null) {
          System.out.println(line);
          stringBuffer.append(line + "\n");
        }
        
        proc.waitFor();

        // Stores the shell output to a field
        synchronized (testOutput) {
          testOutput = stringBuffer.toString();
        }
        
        // Dummy code to demonstrate that a failed test should be indicted by
        // the python code as "ERROR_CODE -1"
        if (testOutput.indexOf("ERROR_CODE -1") != -1) {
          failed = true;
        }        
        in.close();

      }
    } catch (IOException e) {
      e.printStackTrace();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      if (proc != null) {
        proc.destroy();
      }
    }
  }

  public boolean isDaemon() {
    return false;
  }

  public void release() {
    if (proc != null) {
      proc.destroy();
    }
  }

  @Override
  public String toString() {
    return "Test Name:\t\t" + name + "\n"
        + "Number of Retries:\t" + retries + "\n"
        + "Failed:\t\t\t" + failed + "\n" + "Output: \n" + testOutput + "\n";
  }

}
